/* 程序11-8 getpass函数的实现 */
#include <signal.h>
#include <stdio.h>
#include <termios.h>

#define	MAX_PASS_LEN	8		/* max #char for user to enter */

char *getpass(const char *);

int main(void)
{
	char *ptr;

	if ((ptr = getpass("Enter password:")) == NULL) {
		perror("getpass error");
		exit(1);
	}
	printf("password: %s\n", ptr);

	/* now use password (probably encrypt it) ... */

	while (*ptr != 0)
		*ptr++ = 0;		/* zero it out when we're done with it */

	exit(0);
}

char *getpass(const char *prompt)
{
	static char buf[MAX_PASS_LEN + 1];		/* null byte at end */
	char *ptr;
	sigset_t sig, sigsave;
	struct termios term, termsave;
	FILE *fp;
	int c;

	if ((fp = fopen(ctermid(NULL), "r+")) == NULL)
		return(NULL);
	setbuf(fp, NULL);

	sigemptyset(&sig);		/* block SIGINT & SIGTSTP, save signal mask */
	sigaddset(&sig, SIGINT);
	sigaddset(&sig, SIGTSTP);
	sigprocmask(SIG_BLOCK, &sig, &sigsave);

	tcgetattr(fileno(fp), &termsave);		/* save tty state */
	term = termsave;			/* structure copy */
	term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
	tcsetattr(fileno(fp), TCSAFLUSH, &term);

	fputs(prompt, fp);

	ptr = buf;
	while ((c = getc(fp)) != EOF && c != '\n') {
		if (ptr < &buf[MAX_PASS_LEN])
			*ptr++ = c;
	}
	*ptr = 0;		/* null terminate */
	putc('\n', fp);	/* we echo a newline */

					/* restore tty state */
	tcsetattr(fileno(fp), TCSAFLUSH, &termsave);

					/* restore signal mask */
	sigprocmask(SIG_SETMASK, &sigsave, NULL);

	fclose(fp);		/* done with /dev/tty */

	return(buf);
}


